# -*- coding: utf-8 -*-

"""
@file    : _cgroup_node.py
@time    : 2022-10-26 20:05:02
@author  : wenjiachen（陈文嘉）
@version : 1.0
@contact : wenjiachen@tencent.com
@desc    : None
"""

from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

import os

from .subsystems.subsystem_helper import SubsystemHelper


class CGroupNodeValueError(ValueError):
    pass


class CGroupNode(object):
    """
    A CGroupNode that can group together same multiple nodes based on their
    position in the cgroup hierarchy.
    """
    NODE_ROOT = b"root"
    NODE_SUBSYSTEM_ROOT = b"subsystem_root"
    NODE_SLICE = b"slice"
    NODE_SCOPE = b"scope"
    NODE_CGROUP = b"cgroup"

    def __init__(self, name, parent=None):
        if isinstance(name, str):
            name = name.encode()

        self.name = name
        # 暂使用与 name 一致的表达
        self.verbose_name = name
        if parent and not isinstance(parent, CGroupNode):
            raise CGroupNodeValueError("Parent should be another CGroupNode.")

        self.parent = parent
        # 子节点为 List[CGroupNode]，参考 Cgroup 系统的关键数据结构和组织方式
        # https://blog.csdn.net/feelabclihu/article/details/120093236
        self.children = list()
        self.node_type = self._get_node_type()
        self.subsystem_type = self._get_subsystem_type()
        self.subsystem_controller = self._get_subsystem_controller()

    def __eq__(self, other):
        if not isinstance(other, self.__class__):
            return False
        if self.full_path != other.full_path:
            return False

        return True

    def __repr__(self):
        return "<{} {}>".format(self.__class__.__name__, self.path)

    def _get_node_type(self):
        """Returns the current node's type"""
        if self.parent is None:
            return self.NODE_ROOT
        elif self.parent.node_type == self.NODE_ROOT:
            return self.NODE_SUBSYSTEM_ROOT
        elif b".slice" in self.name or b'.partition' in self.name:
            return self.NODE_SLICE
        elif b".scope" in self.name:
            return self.NODE_SCOPE
        else:
            return self.NODE_CGROUP

    def _get_subsystem_type(self):
        """Returns the current node's subsystem type"""
        if (self.node_type == self.NODE_SUBSYSTEM_ROOT and
                self.name in SubsystemHelper.get_subsystem_names()):
            return self.name
        elif self.parent:
            return self.parent.subsystem_type

        return None

    def _get_subsystem_controller(self):
        """Returns the current node's subsystem controller"""
        if self.subsystem_type:
            return SubsystemHelper.get_subsystem_controller(self)
        return None

    @property
    def full_path(self):
        """Absolute system path to the node"""
        if self.parent:
            return os.path.join(self.parent.full_path, self.name)
        return self.name

    @property
    def path(self):
        """Node's relative path from the root node"""
        if not self.parent:
            return b"/"
        # 这里移除了 encode()
        parent_path = self.parent.path
        return os.path.join(parent_path, self.name)

    def create_cgroup(self, name):
        pass

    def delete_cgroup(self, name):
        pass

    def walk(self):
        pass
